/* tftlcd_gpio.c */
#include "bsp_config.h"
#include "chip_syscon_8xx.h"
#include "chip_swm_8xx.h"
#include "chip_gpio_8xx.h"

/* LCD_RST - PIO0_21 */
#define GPIO_LCD_RST_PIN_SHIFT  (21U)
#define GPIO_LCD_RST_PIN_MASK   (1U << GPIO_LCD_RST_PIN_SHIFT)

/* LCD_CS  - PIO0_22 */
#define GPIO_LCD_CS_PIN_SHIFT   (22U)
#define GPIO_LCD_CS_PIN_MASK    (1U << GPIO_LCD_CS_PIN_SHIFT)

/* LCD_RS  - PIO0_23 */
#define GPIO_LCD_RS_PIN_SHIFT   (23U)
#define GPIO_LCD_RS_PIN_MASK    (1U << GPIO_LCD_RS_PIN_SHIFT)

/* LCD_WR  - PIO0_14 */
#define GPIO_LCD_WR_PIN_SHIFT   (14U)
#define GPIO_LCD_WR_PIN_MASK    (1U << GPIO_LCD_WR_PIN_SHIFT)

/* LCD_RD  - PIO0_6  */
#define GPIO_LCD_RD_PIN_SHIFT   (6U)
#define GPIO_LCD_RD_PIN_MASK    (1U << GPIO_LCD_RD_PIN_SHIFT)

/* LCD_D0  - PIO0_12 */
#define GPIO_LCD_D0_PIN_SHIFT    (12U)
#define GPIO_LCD_D0_PIN_MASK     (1U << GPIO_LCD_D0_PIN_MASK)

/* LCD_D1  - PIO0_27 */
#define GPIO_LCD_D1_PIN_SHIFT    (27U)
#define GPIO_LCD_D1_PIN_MASK     (1U << GPIO_LCD_D1_PIN_MASK)

/* LCD_D2  - PIO0_19 */
#define GPIO_LCD_D2_PIN_SHIFT    (19U)
#define GPIO_LCD_D2_PIN_MASK     (1U << GPIO_LCD_D2_PIN_MASK)

/* LCD_D3  - PIO0_12 */
#define GPIO_LCD_D3_PIN_SHIFT    (12U)
#define GPIO_LCD_D3_PIN_MASK     (1U << GPIO_LCD_D3_PIN_MASK)

/* LCD_D4  - PIO0_18 */
#define GPIO_LCD_D4_PIN_SHIFT    (18U)
#define GPIO_LCD_D4_PIN_MASK     (1U << GPIO_LCD_D4_PIN_MASK)

/* LCD_D5  - PIO0_28 */
#define GPIO_LCD_D5_PIN_SHIFT    (28U)
#define GPIO_LCD_D5_PIN_MASK     (1U << GPIO_LCD_D5_PIN_MASK)

/* LCD_D6  - PIO0_16 */
#define GPIO_LCD_D6_PIN_SHIFT    (16U)
#define GPIO_LCD_D6_PIN_MASK     (1U << GPIO_LCD_D6_PIN_MASK)

/* LCD_D7  - PIO0_17 */
#define GPIO_LCD_D7_PIN_SHIFT    (17U)
#define GPIO_LCD_D7_PIN_MASK     (1U << GPIO_LCD_D7_PIN_MASK)

const tbTftLcdDataPins[8] =
{
    GPIO_LCD_D0_PIN_MASK,
    GPIO_LCD_D1_PIN_MASK,
    GPIO_LCD_D2_PIN_MASK,
    GPIO_LCD_D3_PIN_MASK,
    GPIO_LCD_D4_PIN_MASK,
    GPIO_LCD_D5_PIN_MASK,
    GPIO_LCD_D6_PIN_MASK,
    GPIO_LCD_D7_PIN_MASK,
};

void TFTLCD_Init(void);

static void TFTLCD_InitPins(void)
{
    Chip_SYSCON_EnablePeriphClock(SYSCON_AHBPeriphClk_SWM);


    Chip_SYSCON_DisablePeriphClock(SYSCON_AHBPeriphClk_SWM);

    Chip_GPIO_SetPortDirOutput(LPC_GPIO, 0U,  GPIO_LCD_RST_PIN_MASK
                                            | GPIO_LCD_CS_PIN_MASK
                                            | GPIO_LCD_RS_PIN_MASK
                                            | GPIO_LCD_WR_PIN_MASK
                                            | GPIO_LCD_RD_PIN_MASK
                                            | GPIO_LCD_D0_PIN_MASK
                                            | GPIO_LCD_D1_PIN_MASK
                                            | GPIO_LCD_D2_PIN_MASK
                                            | GPIO_LCD_D3_PIN_MASK
                                            | GPIO_LCD_D4_PIN_MASK
                                            | GPIO_LCD_D5_PIN_MASK
                                            | GPIO_LCD_D6_PIN_MASK
                                            | GPIO_LCD_D7_PIN_MASK
                                            );
        );
}

static void TFTLCD_WriteBus(uint8_t dat)
{
    uint8_t dat_set = 0U;
    uint8_t dat_clr = 0U;
    uint8_t i;

    for (i = 0U; i < 8U; i++)
    {
        if (0U != (dat & (1U << i)))
        {
            dat_set |= tbTftLcdDataPins[i];
        }
        else
        {
            dat_clr |= tbTftLcdDataPins[i];
        }
    }
    /* Write data to bus. */
    Chip_GPIO_SetPort(LPC_GPIO, 0U, dat_set);
    Chip_GPIO_ClearPort(LPC_GPIO, 0U, dat_set);

    /* Click the WR to upload. */
    Chip_GPIO_ClearPort(LPC_GPIO, 0U, GPIO_LCD_WR_PIN_MASK);
    Chip_GPIO_SetPort(LPC_GPIO, 0U, GPIO_LCD_WR_PIN_MASK);
}

static void TFTLCD_WriteCmd(uint8_t cmd)
{
    Chip_GPIO_ClearPort(LPC_GPIO, 0U, GPIO_LCD_RS_PIN_MASK); /* LCD_RS = 0. */
    TFTLCD_WriteBus(cmd);
}

static void TFTLCD_WriteData(uint8_t dat)
{
    Chip_GPIO_SetPort(LPC_GPIO, 0U, GPIO_LCD_RS_PIN_MASK); /* LCD_RS = 1. */
    TFTLCD_WriteBus(cmd);
}

static void TFTLCD_DelayMs(uint32_t ms)
{
    volatile uint32_t i, j;

    for (i = 0U; i < ms; i++)
    {
        for (j = 0U; j < 20000U; i++)
        {
            __NOP();
        }
    }

}

void TFTLCD_Init(void)
{
    /* 初始化引脚 */
    TFTLCD_InitPins();

    /* 复位 */
    Chip_GPIO_SetPort(LPC_GPIO, 0U, GPIO_LCD_RST_PIN_MASK);
    TFTLCD_DelayMs(5);
    Chip_GPIO_ClearPort(LPC_GPIO, 0U, GPIO_LCD_RST_PIN_MASK);
    TFTLCD_DelayMs(50);
    Chip_GPIO_SetPort(LPC_GPIO, 0U, GPIO_LCD_RST_PIN_MASK);
    TFTLCD_DelayMs(50);

    /* 片选 */
    Chip_GPIO_SetPort(LPC_GPIO, 0U, GPIO_LCD_CS_PIN_MASK); /* LCD_CS = 1. */
    Chip_GPIO_SetPort(LPC_GPIO, 0U, GPIO_LCD_WR_PIN_MASK); /* LCD_WR = 1. */
    Chip_GPIO_ClearPort(LPC_GPIO, 0U, GPIO_LCD_CS_PIN_MASK); /* LCD_CS = 0. */

    /* 初始化液晶屏寄存器 */
    TFTLCD_WriteCmd(0xE9);
    TFTLCD_WriteData(0x20);

    TFTLCD_WriteCmd(0x11); //Exit Sleep
    TFTLCD_DelayMs(100);
    ///////////////////////////////////////
    TFTLCD_WriteCmd(0xF3); //Set EQ
    TFTLCD_WriteData(0x08);
    TFTLCD_WriteData(0x20);
    TFTLCD_WriteData(0x20);
    TFTLCD_WriteData(0x08);

    TFTLCD_WriteCmd(0xE7);
    TFTLCD_WriteData(0x60);   //OPON
    ///////////////////////////////////////
    TFTLCD_WriteCmd(0xD1);
    TFTLCD_WriteData(0x00);
    TFTLCD_WriteData(0x71);
    TFTLCD_WriteData(0x19);

    TFTLCD_WriteCmd(0xD0);
    TFTLCD_WriteData(0x07);
    TFTLCD_WriteData(0x01);
    TFTLCD_WriteData(0x08);

    TFTLCD_WriteCmd(0x36);
    TFTLCD_WriteData(0x48);

    TFTLCD_WriteCmd(0x3A);
    TFTLCD_WriteData(0x05);

    TFTLCD_WriteCmd(0xC1);
    TFTLCD_WriteData(0x10);
    TFTLCD_WriteData(0x10);
    TFTLCD_WriteData(0x02);
    TFTLCD_WriteData(0x02);

    TFTLCD_WriteCmd(0xC0); //Set Default Gamma
    TFTLCD_WriteData(0x00);
    TFTLCD_WriteData(0x35);
    TFTLCD_WriteData(0x00);
    TFTLCD_WriteData(0x00);
    TFTLCD_WriteData(0x01);
    TFTLCD_WriteData(0x02);

    TFTLCD_WriteCmd(0xC5); //Set frame rate
    TFTLCD_WriteData(0x04);

    TFTLCD_WriteCmd(0xD2); //power setting
    TFTLCD_WriteData(0x01);
    TFTLCD_WriteData(0x44);

    TFTLCD_WriteCmd (0xC8); //Set Gamma
    TFTLCD_WriteData(0x04);
    TFTLCD_WriteData(0x67);
    TFTLCD_WriteData(0x35);
    TFTLCD_WriteData(0x04);
    TFTLCD_WriteData(0x08);
    TFTLCD_WriteData(0x06);
    TFTLCD_WriteData(0x24);
    TFTLCD_WriteData(0x01);
    TFTLCD_WriteData(0x37);
    TFTLCD_WriteData(0x40);
    TFTLCD_WriteData(0x03);
    TFTLCD_WriteData(0x10);
    TFTLCD_WriteData(0x08);
    TFTLCD_WriteData(0x80);
    TFTLCD_WriteData(0x00);

    TFTLCD_WriteCmd (0x2A);
    TFTLCD_WriteData(0x00);
    TFTLCD_WriteData(0x00);
    TFTLCD_WriteData(0x00);
    TFTLCD_WriteData(0xEF);

    TFTLCD_WriteCmd(0x2B);
    TFTLCD_WriteData(0x00);
    TFTLCD_WriteData(0x00);
    TFTLCD_WriteData(0x01);
    //  TFTLCD_WriteData(0x3F);
    TFTLCD_WriteData(0x8F); // on internet

    TFTLCD_WriteCmd(0xCA);  //Set DGC LUT
    TFTLCD_WriteData(0x00);

    TFTLCD_WriteCmd(0xEA);  //Set DGC
    TFTLCD_WriteData(0x80);

    TFTLCD_WriteCmd(0x29); //display on
    TFTLCD_WriteCmd(0x2C); //display on

    Chip_GPIO_SetPort(LPC_GPIO, 0U, GPIO_LCD_CS_PIN_MASK); /* LCD_CS = 1. */
}

void TFTLCD_SetAddress(uint32_t x1, uint32_t y1, uint32_t x2, uint32_t y2)
{
  TFTLCD_WriteCmd(0x2a); // Set_column_address 4 parameters
  TFTLCD_WriteData(x1>>8);
  TFTLCD_WriteData(x1);
  TFTLCD_WriteData(x2>>8);
  TFTLCD_WriteData(x2);

  TFTLCD_WriteCmd(0x2b); // Set_page_address 4 parameters
  TFTLCD_WriteData(y1>>8);
  TFTLCD_WriteData(y1);
  TFTLCD_WriteData(y2>>8);
  TFTLCD_WriteData(y2);

  TFTLCD_WriteCmd(0x2c); // Write_memory_start
}

/* EOF. */

